<script setup lang="ts">
import {
  ElButton,
  ElCascader,
  ElCheckbox,
  ElCheckboxButton,
  ElCheckboxGroup,
  ElDatePicker,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElOption,
  ElRadio,
  ElRadioButton,
  ElRadioGroup,
  ElRate,
  ElSelect,
  ElSlider,
  ElSwitch,
  ElTimePicker,
  ElTimeSelect,
  ElTreeSelect,
  ElUpload,
} from 'element-plus';
import { computed, onMounted, ref, toRefs } from 'vue';

import { IForm } from '@/types';

import SelectWithAll from './SelectWithAll.vue';
import SingleUpload from './SingleUpload.vue';

const props = defineProps<{
  item: IForm;
  data: any;
}>();
const emits = defineEmits<{
  (e: 'update:data', val: any): void;
  (e: 'change'): void;
  (e: 'changeDebounce'): void;
}>();

const { item } = toRefs(props);
const change = () => emits('change');
const changeDebounce = () => emits('changeDebounce');

const apiData = ref([]);

function canUseApiComponent() {
  return (item.value.type === 'treeSelect' || item.value.type === 'select') && item.value.option?.api;
}

onMounted(() => {
  if (canUseApiComponent()) {
    myLoading.value = true;
    item.value.option
      ?.api()
      .then((res: any) => {
        apiData.value = item.value.option?.formatterFn ? item.value.option.formatterFn(res) : res;
      })
      .finally(() => {
        myLoading.value = false;
      });
  }
});

const myLoading = ref(false);

const data = computed({
  get: () => {
    return props.data;
  },
  set: (val) => {
    emits('update:data', val);
  },
});
</script>

<template>
  <el-form-item v-bind="item">
    <el-input v-if="item.type === 'input'" v-model="data" :placeholder="'请输入' + item.label" @input="changeDebounce" v-bind="item.option" />
    <div class="m-text" v-else-if="item.type === 'text'">
      <span>{{ item.option?.textRender ? item.option.textRender(data) : data }}</span>
    </div>
    <el-select
      v-else-if="item.type === 'select'"
      v-model="data"
      :loading="myLoading"
      :placeholder="'请选择' + item.label"
      @change="change"
      v-bind="item.option"
    >
      <el-option
        v-for="e in item?.selectOption?.options || (item.option?.api ? apiData : [])"
        :key="e[item?.selectOption?.value || 'value']"
        :label="e[item?.selectOption?.label || 'label']"
        :value="e[item?.selectOption?.value || 'value']"
        :disabled="e.disabled"
      />
    </el-select>
    <SelectWithAll
      v-else-if="item.type === 'selectWithAll'"
      v-model:value="data"
      :placeholder="'请选择' + item.label"
      :selectOption="item.selectOption"
      @change="change"
      v-bind="item.option"
    />
    <el-radio-group v-else-if="item.type === 'radioGroup'" v-model="data" @change="change" v-bind="item.option">
      <template v-if="item.option?.type === 'button'">
        <el-radio-button
          v-for="e in item?.selectOption?.options || []"
          :key="e[item?.selectOption?.value || 'value']"
          :label="e[item?.selectOption?.label || 'label']"
          :value="e[item?.selectOption?.value || 'value']"
          :disabled="e.disabled"
        />
      </template>
      <template v-else>
        <el-radio
          v-for="e in item?.selectOption?.options || []"
          :key="e[item?.selectOption?.value || 'value']"
          :label="e[item?.selectOption?.label || 'label']"
          :value="e[item?.selectOption?.value || 'value']"
          :disabled="e.disabled"
        />
      </template>
    </el-radio-group>
    <el-checkbox-group v-else-if="item.type === 'checkboxGroup'" v-model="data" @change="change" v-bind="item.option">
      <template v-if="item.option?.type === 'button'">
        <el-checkbox-button
          v-for="e in item?.selectOption?.options || []"
          :key="e[item?.selectOption?.value || 'value']"
          :label="e[item?.selectOption?.label || 'label']"
          :value="e[item?.selectOption?.value || 'value']"
          :disabled="e.disabled"
        />
      </template>
      <template v-else>
        <el-checkbox
          v-for="e in item?.selectOption?.options || []"
          :key="e[item?.selectOption?.value || 'value']"
          :label="e[item?.selectOption?.label || 'label']"
          :value="e[item?.selectOption?.value || 'value']"
          :disabled="e.disabled"
        />
      </template>
    </el-checkbox-group>
    <el-date-picker
      v-else-if="item.type === 'datePicker'"
      v-model="data"
      :placeholder="'请选择' + item.label"
      start-placeholder="开始日期"
      end-placeholder="结束日期"
      @change="change"
      v-bind="item.option"
    />
    <el-time-picker
      v-else-if="item.type === 'timePicker'"
      v-model="data"
      :placeholder="'请选择' + item.label"
      start-placeholder="开始时间"
      end-placeholder="结束时间"
      @change="change"
      v-bind="item.option"
    />
    <el-time-select
      v-else-if="item.type === 'timeSelect'"
      v-model="data"
      :placeholder="'请选择' + item.label"
      @change="change"
      v-bind="item.option"
    />
    <el-switch v-else-if="item.type === 'switch'" v-model="data" @change="change" v-bind="item.option" />
    <el-rate v-else-if="item.type === 'rate'" @change="change" v-model="data" />
    <el-input-number
      v-else-if="item.type === 'number'"
      v-model="data"
      :placeholder="'请选择' + item.label"
      @change="change"
      controlsPosition="right"
      v-bind="item.option"
    />
    <el-cascader v-else-if="item.type === 'cascader'" v-model="data" :placeholder="'请输入' + item.label" @change="change" v-bind="item.option" />
    <el-slider v-else-if="item.type === 'slider'" v-model="data" @change="change" v-bind="item.option" />
    <el-upload v-else-if="item.type === 'upload'" v-model:file-list="data" @change="change" v-bind="item.option">
      <el-button type="primary">选择文件</el-button>
    </el-upload>
    <SingleUpload v-else-if="item.type === 'singleUpload'" v-model:value="data" :config="item" />
    <el-checkbox
      v-else-if="item.type === 'checkbox'"
      v-model="data"
      @change="change"
      :label="item?.option?.label || ''"
      v-bind="item.option"
    ></el-checkbox>
    <el-tree-select
      v-else-if="item.type === 'treeSelect'"
      :loading="myLoading"
      v-model="data"
      :data="apiData"
      :placeholder="'请选择' + item.label"
      @change="change"
      v-bind="item.option"
    />
    <slot v-else :name="item.prop"></slot>
  </el-form-item>
</template>

<style scoped>
.m-text {
  display: flex;
  align-items: center;
  height: 100%;
  width: 100%;
}
.m-text > span {
  line-height: initial;
}
.form-upload-single > :deep(.el-input-group__append) {
  padding: 0 10px;
  color: var(--el-text-color-primary);
}
:deep(.el-input__inner) {
  text-align: left;
}
</style>
